home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-10 | 32.8 KB | 1,310 lines |
- Newsgroups: comp.sources.unix
- From: rccarel@urc.tue.nl (Carel Braam)
- Subject: v26i119: opcom-2.1 - permit unprivileged users to run selected commands, Part01/01
- Sender: unix-sources-moderator@vix.com
- Approved: paul@vix.com
-
- Submitted-By: rccarel@urc.tue.nl (Carel Braam)
- Posting-Number: Volume 26, Issue 119
- Archive-Name: opcom-2.1/part01
-
- Opcom is a program, that enables users, belonging to a special group to
- execute a limited set of commands with another userid or groupid. This
- makes it possible to perform daily system administration tasks without
- having the full privileges of root. It is also possible to use opcom to
- execute shell scripts with privileges without having to rely on insecure
- suid-scripts.
-
- rccarel@urc.tue.nl (Carel Braam)
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: ENHANCEMENTS MANIFEST Makefile README UNSHAR.HDR config
- # detab.c opcom.c srctoman sysdep
- # Wrapped by vixie@gw.home.vix.com on Sun Apr 11 01:55:17 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'ENHANCEMENTS' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ENHANCEMENTS'\"
- else
- echo shar: Extracting \"'ENHANCEMENTS'\" \(1375 characters\)
- sed "s/^X//" >'ENHANCEMENTS' <<'END_OF_FILE'
- X Opcom release 2.1 enhancements
- X ==============================
- X
- X
- X
- X- Root is assumed to belong to all groups, so he is allowed to execute all
- X opcom-commands.
- X
- X- If a userid was not mentioned in /etc/group with the group assigned to him
- X in /etc/passwd, he was not allowed to execute commands for that group.
- X This has been fixed.
- X
- X- The effective groupid is now also used to determine whether the user is
- X allowed to execute a command.
- X
- X- In this version it is also possible to define opcom-commands that can
- X be called by any userid. In that case operator-group must be an '*'.
- X This makes it possible to write shell scripts that will be executed with
- X root privileges. So the use of suid-shell scripts (a serious security hole)
- X can be avoided.
- X
- X- If opcom is called without arguments, the list of valid commands is printed.
- X
- X- The manual page has been moved from chapter 8 to chapter 1.
- X
- X- Optionally opcom usage is reported via syslogd(8). See README and config
- X for details.
- X
- X- The environment is cleared before the environment variables are set to the
- X values mentioned in opcom(1).
- X
- X- If opcom is not running with root as effective user, a warning is printed.
- X This to facilitate debugging.
- X
- X- All typed functions now return values. This improves portability.
- X
- X- Some elementary checking is done on the argument list.
- X
- X
- X Carel Braam, january 1991
- END_OF_FILE
- if test 1375 -ne `wc -c <'ENHANCEMENTS'`; then
- echo shar: \"'ENHANCEMENTS'\" unpacked with wrong size!
- fi
- # end of 'ENHANCEMENTS'
- fi
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(424 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X-----------------------------------------------------------
- X ENHANCEMENTS 1
- X MANIFEST 1 This shipping list
- X Makefile 1
- X README 1
- X UNSHAR.HDR 1
- X config 1
- X detab.c 1
- X opcom.c 1
- X srctoman 1
- X sysdep 1
- END_OF_FILE
- if test 424 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(1926 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X#++
- X# NAME
- X# Makefile
- X# SUMMARY
- X# makefile for opcom.
- X# AUTHOR(S)
- X#
- X# Carel Braam (rccarel@urc.tue.nl)
- X# Eindhoven University of Technology
- X# Computing Centre
- X# Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X# CREATION DATE
- X# Thu Jan 5 10:41:57 MET 1989
- X# LAST MODIFICATION
- X# Thu Jan 10 10:02:53 MET 1991
- X# VERSION/RELEASE
- X# 2.1
- X#--
- X
- X# System dependent variables
- X
- CC = cc
- CDEFS =
- CFLAGS =
- LFLAGS = -h
- BINDIR = /usr/local/bin
- MANDIR = /usr/local/man
- X
- X# End system dependent variables
- X
- CSOURCES = opcom.c
- HFILES = sysdep
- SHELLS = config
- MAKEFILES = Makefile
- OPSOURCES = $(CSOURCES) $(HFILES) $(SHELLS) $(MAKEFILES) ENHANCEMENTS README
- USOURCES = detab.c srctoman
- SOURCES = $(OPSOURCES) $(USOURCES)
- X
- all: opcom
- X
- sysdep.h: sysdep config
- X sh config sysdep >sysdep.h
- X
- man: opcom.1
- X
- opcom.1: opcom.c config detab
- X sh srctoman -L opcom.c | sh config >opcom.1
- X
- X# Lint.
- X
- lint: sysdep.h
- X lint $(LFLAGS) $(CDEFS) opcom.c
- X
- X
- detab: detab.c
- X $(CC) $(CFLAGS) $(CDEFS) detab.c -o detab
- X
- opcom: opcom.c sysdep.h
- X $(CC) $(CFLAGS) $(CDEFS) opcom.c -o opcom
- X
- X# Installation and update.
- X
- install: opcom
- X cp opcom $(BINDIR)
- X cd $(BINDIR); chown root opcom; chmod u+s opcom
- X
- installman: man
- X cp opcom.1 $(MANDIR)/man1
- X rm -f $(MANDIR)/cat1/opcom.1
- X
- archive: $(OPSOURCES)
- X archive $(OPSOURCES)
- X
- release: $(OPSOURCES)
- X modsource +1 $(CSOURCES)
- X modsource +2 $(CSOURCES)
- X modsource +1 -c $(HFILES)
- X modsource +2 -c $(HFILES)
- X modsource +1 -mk $(MAKEFILES) README
- X modsource +2 -mk $(MAKEFILES) README
- X modsource +1 - $(SHELLS)
- X modsource +2 - $(SHELLS)
- X archive $(OPSOURCES)
- X
- version: $(OPSOURCES)
- X modsource -1 $(CSOURCES)
- X modsource -1 -c $(HFILES)
- X modsource -1 -mk $(MAKEFILES) README
- X modsource -1 - $(SHELLS)
- X archive $(OPSOURCES)
- X
- shar: $(SOURCES)
- X rm -f Part?? Part??.Z
- X makekit $(SUBDIRS) $(SOURCES) $(DIRENT)
- X
- clean:
- X -rm -f *.BAK *.o opcom detab opcom.1 tmp.* sysdep.h \
- X nohup.out core Part?? Part??.Z
- END_OF_FILE
- if test 1926 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(2058 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- Opcom is a program, that enables users, belonging to a special group to
- execute a limited set of commands with another userid or groupid.
- This makes it possible to perform daily system administration tasks without
- having the full privileges of root.
- It is also possible to use opcom to execute shell scripts with privileges
- without having to rely on insecure suid-scripts.
- X
- X
- Carel Braam
- X
- internet: rccarel@urc.tue.nl | Computing Centre
- bitnet: rccarel@heitue5.BITNET | Eindhoven University of Technology
- phone: 040-472158 | Den Dolech 2, P.O. Box 513
- home: 040-810381 | 5600 MB Eindhoven, The Netherlands
- X
- X
- X INSTALLATION NOTES
- X ==================
- X
- Before you start off adapt the file config to your local needs.
- All system dependent variables are set between the comment
- X
- X# *** System dependent variables ***
- X
- and the comment
- X
- X# *** End system dependent variables ***
- X
- Currently the following variables can be set:
- X
- SYSTEM Set SYSTEM to BSD for bsd systems and to SYSV for system v.
- SYSLOG Set SYSLOG to USE_SYSLOG if you want to report opcom usage via
- X syslogd(8) and to NO_SYSLOG otherwise.
- X SYSLOG must also be set to NO_SYSLOG if your system does not
- X support syslogd(8).
- OPCOMDIR The directory for the files COMMANDS and PROFILE.
- COMMANDS The file containing the commands, that are allowed.
- PROFILE The file containing the profile to be executed.
- X
- As well the manual page opcom.1 as sysdep.h are dependent on config.
- To make opcom just enter make.
- The manual page can be created by entering make man.
- Then as super user type "make install" to install opcom and "make installman"
- to install the manual page.
- See the makefile for the definition of the local bin directory and the local
- manual directory.
- X
- X#++
- X# AUTHOR(S)
- X#
- X# Carel Braam (rccarel@urc.tue.nl)
- X# Eindhoven University of Technology
- X# Computing Centre
- X# Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X# CREATION DATE
- X# Thu Jan 5 11:25:04 MET 1989
- X# LAST MODIFICATION
- X# Thu Jan 10 10:02:54 MET 1991
- X# VERSION/RELEASE
- X# 2.1
- X#--
- END_OF_FILE
- if test 2058 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'UNSHAR.HDR' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'UNSHAR.HDR'\"
- else
- echo shar: Extracting \"'UNSHAR.HDR'\" \(1141 characters\)
- sed "s/^X//" >'UNSHAR.HDR' <<'END_OF_FILE'
- Return-Path: root@tue.nl
- Received: by cognition.pa.dec.com; id AA07850; Fri, 29 May 92 02:27:07 -0700
- Received: by inet-gw-2.pa.dec.com; id AA29935; Fri, 29 May 92 02:24:41 -0700
- Received: from tuegate.tue.nl by sun4nl.nluug.nl with SMTPid AA14982 (5.65b/CWI-3.3); Fri, 29 May 1992 11:23:05 +0200
- Received: by tuegate.tue.nl id AA23498 (5.65c/IDA-1.4.4 for nluug.nl!comp-sources-unix); Fri, 29 May 1992 11:25:47 +0200
- To: comp-sources-unix@nluug.nl
- Path: tuegate.tue.nl!rc6.urc.tue.nl!rccarel
- XFrom: rccarel@rc6.urc.tue.nl (Carel Braam)
- Newsgroups: comp.sources.unix
- Subject: opcom - execute an operator command
- Message-Id: <rccarel.707131492@rc6.urc.tue.nl>
- Date: 29 May 92 09:24:52 GMT
- Sender: root@tue.nl
- Reply-To: rccarel@urc.tue.nl
- Lines: 1241
- X
- X
- X
- Version 2.1 of opcom was posted before, but it never showed up. So I
- post it again, because this version is more secure than the previous one.
- One of the enhancements is that creates a complete new environment so
- that no original environment variable is retained (see CERT advisory of
- May 27, 1992).
- X
- X Carel Braam
- X Eindhoven University of Technology
- X The Netherlands
- X
- END_OF_FILE
- if test 1141 -ne `wc -c <'UNSHAR.HDR'`; then
- echo shar: \"'UNSHAR.HDR'\" unpacked with wrong size!
- fi
- # end of 'UNSHAR.HDR'
- fi
- if test -f 'config' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'config'\"
- else
- echo shar: Extracting \"'config'\" \(1053 characters\)
- sed "s/^X//" >'config' <<'END_OF_FILE'
- X: use /bin/sh
- X
- X# opcom configuration script.
- X#
- X# In the first part of this script the directories and the administration
- X# for opcom are defined.
- X# Refer to all of these only by the environment variables defined here.
- X
- X#++
- X# AUTHOR(S)
- X#
- X# Carel Braam (rccarel@urc.tue.nl)
- X# Eindhoven University of Technology
- X# Computing Centre
- X# Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X# CREATION DATE
- X# Thu Jan 5 11:09:45 MET 1989
- X# LAST MODIFICATION
- X# Thu Jan 10 10:02:54 MET 1991
- X# VERSION/RELEASE
- X# 2.1
- X#--
- X
- X# *** System dependent variables ***
- X
- SYSTEM=BSD # must be BSD or SYSV (system v)
- X#SYSTEM=SYSV # must be BSD or SYSV (system v)
- SYSLOG=USE_SYSLOG # report opcom usage to syslogd
- X#SYSLOG=NO_SYSLOG # don't report opcom usage
- X
- OPCOMDIR="/usr/local/lib/opcom"
- COMMANDS="$OPCOMDIR/commands" # command file
- PROFILE="$OPCOMDIR/profile" # profile
- X
- X# *** End system dependent variables ***
- X
- sed 's%XCOMMANDS%'"$COMMANDS"'%g
- X s%XPROFILE%'"$PROFILE"'%g
- X s%XSYSLOG%'"$SYSLOG"'%g
- X s%XSYSTEM%'"$SYSTEM"'%g' $*
- END_OF_FILE
- if test 1053 -ne `wc -c <'config'`; then
- echo shar: \"'config'\" unpacked with wrong size!
- fi
- # end of 'config'
- fi
- if test -f 'detab.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'detab.c'\"
- else
- echo shar: Extracting \"'detab.c'\" \(1053 characters\)
- sed "s/^X//" >'detab.c' <<'END_OF_FILE'
- X/*++
- X/* NAME
- X/* detab 1
- X/* SUMMARY
- X/* expand tabs to blanks
- X/* PROJECT
- X/* documentation
- X/* SYNOPSIS
- X/* detab
- X/* DESCRIPTION
- X/* Detab is a filter that expands tab stops in its standard input
- X/* to blanks. A tab stop distance of eight blanks is assumed.
- X/* BUGS
- X/* This program does not handle backspaces.
- X/* AUTHOR(S)
- X/* Wietse Venema
- X/* Eindhoven University of Technology
- X/* Department of Mathematics and Computer Science
- X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X/* CREATION DATE
- X/* Sep 14 1985
- X/* LAST MODIFICATION
- X/* Mon May 4 20:32:48 GMT+1:00 1987
- X/* VERSION/RELEASE
- X/* 1.3
- X/*--*/
- X
- X#include <stdio.h>
- X
- X#define BLANK ' '
- X
- main()
- X{
- X register int c; /* character buffer */
- X register int ccount = 0; /* nr of characters printed on current line */
- X
- X while ((c = getchar()) != EOF) {
- X switch (c) {
- X
- X case '\r':
- X case '\n': putchar(c);
- X ccount = 0;
- X break;
- X
- X case '\t': do { putchar(BLANK); } while (++ccount & 7);
- X break;
- X
- X default: putchar(c);
- X ccount++;
- X break;
- X }
- X }
- X exit(0);
- X}
- END_OF_FILE
- if test 1053 -ne `wc -c <'detab.c'`; then
- echo shar: \"'detab.c'\" unpacked with wrong size!
- fi
- # end of 'detab.c'
- fi
- if test -f 'opcom.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'opcom.c'\"
- else
- echo shar: Extracting \"'opcom.c'\" \(13362 characters\)
- sed "s/^X//" >'opcom.c' <<'END_OF_FILE'
- X/*++
- X/* NAME
- X/* opcom 1
- X/* SUMMARY
- X/* execute an operator command.
- X/* SYNOPSIS
- X/* .fi
- X/* .B opcom
- X/* command [ arguments ]
- X/* DESCRIPTION
- X/* .I Opcom
- X/* enables users belonging to a special group (as defined in /etc/group)
- X/* to execute a limited set of commands with another userid (e.g. root)
- X/* or groupid. The file
- X/* .I XCOMMANDS
- X/* describes which commands are allowed for which groups and which
- X/* userid (groupid) will be used.
- X/* .br
- X/* .I Command
- X/* is a valid operator command if it matches an entry in
- X/* .I XCOMMANDS.
- X/* Those entries have the following form:
- X/*
- X/* path-name : operator-group : [ new-userid ] [ : [ new-groupid ]]
- X/*
- X/* .I Command
- X/* matches an entry, if it is the basename of
- X/* .I path-name
- X/* and if at least one of the following conditions holds:
- X/* .IP \- 2.4
- X/* .I operator-group
- X/* is "*".
- X/* .IP \- 2.4
- X/* The real userid executing
- X/* .I opcom
- X/* is a member of the group
- X/* .I operator-group
- X/* (as defined in /etc/group).
- X/* .IP \- 2.4
- X/* The default group of the real userid, as defined in /etc/passwd,
- X/* is equal to
- X/* .I operator-group.
- X/* .IP \- 2.4
- X/* The effective groupid is that of
- X/* .I operator-group.
- X/* .RE
- X/*
- X/* If
- X/* .I command
- X/* matches more than one entry, the first matching entry is selected.
- X/* This allows multiple levels of privilege.
- X/* If no match is found,
- X/* .I opcom
- X/* aborts with the message "access denied.".
- X/*
- X/* The matching command is executed with the given
- X/* .I arguments
- X/* unless they contain characters which are special to /bin/sh (e.g. ;).
- X/* .br
- X/* If
- X/* .I new-userid (new-groupid)
- X/* is not empty, the effective and real userid (groupid) are set to
- X/* .I new-userid (new-groupid).
- X/* .br
- X/* If
- X/* .I new-userid (new-groupid)
- X/* is empty, the effective and real userid (groupid)
- X/* are set to the real userid (groupid).
- X/*
- X/* The current environment is cleared and the following environment
- X/* variables are set:
- X/* .IP \- 2.4
- X/* COMMAND to
- X/* .I command.
- X/* .IP \-
- X/* ORGGROUP to the group name of the real groupid of the invoker of
- X/* .I opcom.
- X/* .IP \-
- X/* GROUP to the group name of the real groupid executing
- X/* .I command.
- X/* .IP \-
- X/* IFS to blank, tab and new line.
- X/* .IP \-
- X/* ORGUSER to the login name of the real userid of the invoker of
- X/* .I opcom.
- X/* .IP \-
- X/* PATH to /
- X/* .IP \-
- X/* USER and LOGNAME to the login name of the real userid executing
- X/* .I command.
- X/* .RE
- X/*
- X/* If the script
- X/* .I XPROFILE
- X/* exists, this script will be executed
- X/* within the (Bourne) shell that executes
- X/* .I command.
- X/* So changes to the environment (e.g. PATH) can be put there.
- X/*
- X/* If
- X/* .I opcom
- X/* is called with no arguments, a list of valid commands for the
- X/* user executing
- X/* .I opcom
- X/* is printed.
- X/* FILES
- X/* XCOMMANDS
- X/* XPROFILE
- X/* /etc/group
- X/* /etc/passwd
- X/* CAVEAT
- X/* Beware of Trojan horses: don't allow commands with shell escapes.
- X/* BUGS
- X/* Invalid entries in
- X/* .I XCOMMANDS
- X/* are skipped without warning.
- X/* DIAGNOSTICS
- X/* In case of error
- X/* .I opcom
- X/* prints an error message on standard error and terminates
- X/* with nonzero status.
- X/* .br
- X/* Commands executed by \fIopcom\fP are optionally reported via syslogd(8).
- X/* EXAMPLES
- X/*
- X/*
- X/* .I XCOMMANDS:
- X/*
- X/* .nf
- X/* .ft C
- X/* /bin/fsck:operators:root
- X/* /bin/dump:operators:root
- X/* /bin/kill:operators:root
- X/* /etc/lpc:operators:root
- X/* /usr/ucb/lprm:operators:root
- X/* /bin/mount:operators:root
- X/* /bin/restore:operators:root
- X/* /bin/shutdown:operators:root
- X/* /bin/umount:operators:root
- X/* /mgt/cas/bin/menu:ucadmin:root
- X/* /usr/local/bin/lp-cancel:bcf:daemon:daemon
- X/* /usr/local/bin/lp-move:bcf:daemon:daemon
- X/* /usr/local/bin/lp-force:bcf:daemon:daemon
- X/* /usr/local/bin/lp-sched:bcf:daemon:daemon
- X/* /usr/local/bin/lp-shut:bcf:daemon:daemon
- X/* /usr/local/lib/opcom/testenv:*:
- X/*
- X/* .ft
- X/* Invocation examples:
- X/*
- X/* opcom lpc start lp
- X/* opcom shutdown
- X/* opcom lp-shut
- X/* opcom testenv
- X/* AUTHOR(S)
- X/*
- X/* Carel Braam (rccarel@urc.tue.nl)
- X/* Eindhoven University of Technology
- X/* Computing Centre
- X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X/* BUG REPORTS TO
- X/* rccarel@urc.tue.nl
- X/* CREATION DATE
- X/* Wed Jan 4 14:12:59 MET 1989
- X/* LAST MODIFICATION
- X/* Thu Jan 10 10:02:52 MET 1991
- X/* VERSION/RELEASE
- X/* 2.1
- X/*--*/
- X
- X#include <stdio.h>
- X#include "sysdep.h"
- X#include <grp.h>
- X#include <pwd.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <varargs.h>
- X#include <ctype.h>
- X#ifdef USE_SYSLOG
- X#include <syslog.h>
- extern int openlog ();
- extern void syslog ();
- X#endif
- X
- extern void exit ();
- extern void perror ();
- extern int errno;
- extern char *sys_errlist [];
- extern int sys_nerr;
- X
- extern int getegid ();
- extern int geteuid ();
- extern int getgid ();
- extern int setuid ();
- extern struct group *getgrgid ();
- extern struct group *getgrnam ();
- extern struct passwd *getpwnam ();
- extern struct passwd *getpwuid ();
- extern char *malloc ();
- extern int system ();
- X
- X#define WARN 0
- X#define ABORT 1
- X
- struct command {
- X char name [64];
- X char path [1024];
- X char group [32];
- X char new_group [32];
- X char new_user [32];
- X};
- X
- void PERROR ();
- int check_group ();
- int copy_args ();
- void display_commands ();
- void error ();
- void exec_cmnd ();
- struct command *get_command ();
- struct command *parse_command ();
- X
- XFILE *command_file;
- int my_egid,
- X my_gid,
- X my_euid,
- X my_uid;
- char orguser [32] = {0};
- char orggroup [32] = {0};
- char *nextitem ();
- void set_env ();
- void set_ids ();
- X
- char *progname; /* used for diagnostics */
- X
- main (argc, argv)
- int argc;
- char **argv;
- X{
- X int fd;
- X struct command *command;
- X struct group *group;
- X struct passwd *passwd;
- X
- X /* close all file descriptors > 2 */
- X for (fd = 3; fd <= _NFILE; fd++)
- X (void) close (fd);
- X if (progname = strrchr (*argv, '/'))
- X progname++;
- X else
- X progname = *argv;
- X argv++;
- X argc--;
- X
- X my_euid = geteuid();
- X if (my_euid != 0)
- X error (WARN, "Warning: the effective userid is not root.");
- X my_uid = getuid();
- X if ((passwd = getpwuid (my_uid)) == NULL)
- X error (ABORT, "cannot find passwd entry for userid %d.", my_uid);
- X (void) strcpy (orguser, passwd->pw_name);
- X
- X my_egid = getegid();
- X my_gid = getgid();
- X if ((group = getgrgid (my_gid)) != NULL)
- X (void) strcpy (orggroup, group->gr_name);
- X
- X if ((command_file = fopen (COMMANDS, "r")) == NULL)
- X error (ABORT, "cannot open %s for reading.", COMMANDS);
- X if (argc == 0) {
- X display_commands ();
- X exit (0);
- X }
- X
- X command = get_command (*argv);
- X set_ids (command->new_user, command->new_group);
- X (void) fclose (command_file);
- X exec_cmnd (command, argc-1, argv+1);
- X return (0); /* makes lint happy */
- X}
- X
- void display_commands ()
- X{
- X struct command *command;
- X int first = 1;
- X int printit;
- X
- X while ((command = parse_command ()) != NULL) {
- X if (my_uid == 0) { /* root has access to all commands */
- X printit = 1;
- X } else {
- X printit = check_group (command->group);
- X }
- X if (printit) {
- X if (first) {
- X first = 0;
- X (void) printf ("Valid opcom commands are:\n\n");
- X }
- X (void) printf ("%s (group %s)\n", command->name, command->group);
- X }
- X }
- X if (first) /* We didn't find valid commands */
- X error (ABORT, "access denied.");
- X}
- X
- X
- struct command *get_command (name)
- char *name;
- X{
- X struct command *command;
- X
- X while ((command = parse_command ()) != NULL) {
- X if (strcmp (name, command->name) == 0) {
- X if (my_uid == 0) /* root has access to all commands */
- X return (command);
- X if (check_group (command->group))
- X return (command);
- X }
- X }
- X error (ABORT, "access denied.");
- X return (NULL);
- X}
- X
- struct command *parse_command ()
- X{
- X static char cmndbuf [BUFSIZ];
- X static struct command command;
- X char ch,
- X *cmnd,
- X *pc,
- X *ptail,
- X *pt;
- X
- X while (fgets (cmndbuf, BUFSIZ, command_file) != NULL) {
- X for (cmnd = cmndbuf; isspace (*cmnd); cmnd++);
- X pt = command.path;
- X ptail = cmnd;
- X while (! (isspace (ch = *ptail) || (ch == ':') || (ch == 0))) {
- X *pt++ = ch;
- X ptail++;
- X }
- X *pt = 0;
- X while (isspace (*ptail))
- X ptail++;
- X if (*ptail != ':') /* invalid entry */
- X continue;
- X pt = command.path;
- X if ((pc = strrchr (pt, '/')) == NULL)
- X pc = pt;
- X else
- X pc++;
- X (void) strcpy (command.name, pc);
- X ptail = nextitem (ptail+1, command.group);
- X ptail = nextitem (ptail, command.new_user);
- X ptail = nextitem (ptail, command.new_group);
- X return (&command);
- X }
- X return (NULL);
- X}
- X
- char *nextitem (pstart, target)
- char *pstart,
- X *target;
- X{
- X char ch,
- X *ps = pstart,
- X *pt = target;
- X
- X while (isspace (*ps))
- X ps++;
- X if (*ps == 0) {
- X *pt = 0;
- X return (ps);
- X }
- X for (ch = *ps; (ch != ':') & (ch != 0); ch = *++ps)
- X *pt++ = ch;
- X *pt-- = 0;
- X for (ch = *pt; isspace (ch); ch = *pt--)
- X *pt = 0;
- X if (*ps == 0)
- X return (ps);
- X else
- X return (ps+1);
- X}
- X
- int check_group (groupname)
- char *groupname;
- X{
- X char **gr_list;
- X struct group *group;
- X
- X if (strcmp (groupname, "*") == 0) /* matches everything */
- X return (1);
- X if ((group = getgrnam (groupname)) != NULL) {
- X if (my_egid == group->gr_gid) /* effective groupid */
- X return (1);
- X for (gr_list = group->gr_mem; *gr_list != NULL; gr_list++) {
- X if (strcmp (orguser, *gr_list) == 0)
- X return (1);
- X }
- X }
- X return (0);
- X}
- X
- void set_ids (new_user, new_group)
- char *new_user,
- X *new_group;
- X{
- X struct group *group;
- X struct passwd *passwd;
- X
- X if (*new_group != 0) {
- X /* not empty, must be set before uid is set */
- X if ((group = getgrnam (new_group)) == NULL)
- X error (ABORT, "cannot find group entry for groupid %s.", new_group);
- X if (setgid (group->gr_gid) < 0)
- X PERROR (ABORT);
- X }
- X if (*new_user != 0) { /* not empty */
- X if ((passwd = getpwnam (new_user)) == NULL)
- X error (ABORT, "cannot find passwd entry for userid %s.", new_user);
- X if (setuid (passwd->pw_uid) < 0)
- X PERROR (ABORT);
- X } else if (setuid (getuid ()) < 0)
- X PERROR (ABORT);
- X}
- X
- void exec_cmnd (command, argc, argv)
- struct command *command;
- int argc;
- char **argv;
- X{
- X unsigned cmnd_size = 0;
- X int i,
- X rslt;
- X struct stat prstat;
- X char
- X special,
- X *args,
- X *cmnd,
- X *pa,
- X *pc;
- X
- X set_env (command->name, command->new_group, command->new_user);
- X cmnd_size = strlen (command->path)+32;
- X for (i = 0; i < argc; i++)
- X cmnd_size += strlen (argv [i])+1;
- X pc = cmnd = malloc (cmnd_size+strlen (PROFILE));
- X if ((stat (PROFILE, &prstat) == 0) && (prstat.st_mode & 0400)) {
- X /* We must execute the profile */
- X (void) sprintf (pc, ". %s;", PROFILE);
- X pc += strlen (pc);
- X }
- X pa = command->path;
- X while (*pa != 0)
- X *pc++ = *pa++;
- X *pc++ = ' ';
- X args = pc;
- X special = copy_args (argc, argv, args);
- X
- X#ifdef USE_SYSLOG
- X# ifdef LOG_AUTH
- X (void) openlog (progname, LOG_PID, LOG_AUTH);
- X# else
- X (void) openlog (progname, LOG_PID);
- X# endif /* LOG_AUTH */
- X syslog (LOG_NOTICE, "%s: \"%s %s\"", orguser, command, args);
- X#endif USE_SYSLOG
- X
- X if (special != 0) /* Special characters are not allowed */
- X error (ABORT, "'%c' illegal in argument list.", special);
- X if ((rslt = system (cmnd)) < 0)
- X PERROR (ABORT);
- X exit (rslt);
- X}
- X
- int copy_args (argc, argv, args)
- int argc;
- char **argv;
- char *args;
- X{
- X char *pa,
- X special = 0;
- X
- X while (argc-- > 0) {
- X for (pa = *argv++; *pa != 0; pa++) {
- X *args++ = *pa;
- X /* Look for special characters and return the first one. */
- X if (special == 0) {
- X switch (*pa & 0177) {
- X case ';':
- X case '>':
- X case '`':
- X case '&':
- X case '|':
- X case '^':
- X case '\n':
- X special = *pa; /* We got one */
- X }
- X }
- X }
- X *args++ = ' ';
- X }
- X *args = 0; /* close string */
- X return (special);
- X
- X}
- X
- void set_env (name, new_group, new_user)
- char *name,
- X *new_group,
- X *new_user;
- X{
- X extern char **environ;
- X
- X static char envbuf [2048] = {0};
- X char *penv = envbuf;
- X static char *newenv [16] = {0};
- X int next = 0;
- X
- X#define put_env {newenv [next++] = penv; penv += strlen (penv) + 1;}
- X
- X (void) sprintf (penv, "IFS= \t\n");
- X put_env;
- X (void) sprintf (penv, "PATH=/");
- X put_env;
- X (void) sprintf (penv, "COMMAND=%s", name);
- X if (orggroup [0] != 0) {
- X (void) sprintf (penv, "ORGGROUP=%s", orggroup);
- X put_env;
- X }
- X if (new_group [0] != 0) {
- X (void) sprintf (penv, "GROUP=%s", new_group);
- X put_env;
- X }
- X (void) sprintf (penv, "ORGUSER=%s", orguser);
- X put_env;
- X if (*new_user == 0) {
- X (void) sprintf (penv, "USER=%s", orguser);
- X put_env;
- X (void) sprintf (penv, "LOGNAME=%s", orguser);
- X put_env;
- X } else {
- X (void) sprintf (penv, "USER=%s", new_user);
- X put_env;
- X (void) sprintf (penv, "LOGNAME=%s", new_user);
- X put_env;
- X }
- X environ = newenv;
- X}
- X
- void PERROR (why)
- int why;
- X{
- X perror (progname);
- X if (why == ABORT)
- X exit (1);
- X}
- X
- X/* error - barf and quit */
- X
- X/* VARARGS1 */
- X
- void error (va_alist)
- va_dcl
- X{
- X va_list s;
- X int why;
- X char *fmt;
- X
- X va_start(s);
- X
- X why = va_arg (s, int);
- X fmt = va_arg (s, char *);
- X (void) fprintf (stderr, "%s: ", progname);
- X for (/* void */; *fmt; fmt++) {
- X if (*fmt != '%') {
- X (void) putc(*fmt,stderr);
- X } else if (*++fmt == 's') {
- X (void) fputs(va_arg(s,char *),stderr);
- X } else if (*fmt == 'c') {
- X (void) putc(va_arg(s,int),stderr);
- X } else if (*fmt == 'u') {
- X (void) fprintf(stderr,"%u",va_arg(s,unsigned));
- X } else if (*fmt == 'd') {
- X (void) fprintf(stderr,"%d",va_arg(s,int));
- X }
- X }
- X va_end(s);
- X (void) fprintf (stderr, "\n");
- X if (why != WARN)
- X exit (why);
- X (void) fflush (stderr);
- X}
- END_OF_FILE
- if test 13362 -ne `wc -c <'opcom.c'`; then
- echo shar: \"'opcom.c'\" unpacked with wrong size!
- fi
- # end of 'opcom.c'
- fi
- if test -f 'srctoman' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'srctoman'\"
- else
- echo shar: Extracting \"'srctoman'\" \(4703 characters\)
- sed "s/^X//" >'srctoman' <<'END_OF_FILE'
- X: srctoman - see comment below
- X
- X: process arguments
- X
- LOCAL=
- HOST=
- while :
- do
- X case $1 in
- X -L) HOST=`hostname`;
- X HOST=`expr $HOST : '\([^.]*\)' | tr "[a-z]" "[A-Z]"`
- X LOCAL=LOCAL;;
- X [0-9]) SECT=$1;;
- X -) LANG=$1; B='[#:]';;
- X -awk) LANG=$1; B='#';;
- X -c) LANG=$1; B='\/\*';;
- X -f) LANG=$1; B='[Cc]';;
- X -mk) LANG=$1; B='#';;
- X -n|-t) LANG=$1; B='\\"';;
- X -p) LANG=$1; B='{';;
- X -r) LANG=$1; B='#';;
- X -C) LANG=$1; B=$2; shift;;
- X -*) ERROR="unknown option: $1"; break;;
- X "") ERROR="missing file argument"; break;;
- X *) break;;
- X esac
- X shift
- done
- X
- X: check error status
- X
- case $ERROR in
- X"") ;;
- X *) echo "$0: $ERROR" 1>&2
- X echo "usage: $0 [-|-awk|-c|-f|-mk|-n|-p|-t|-r] [section] file(s)" 1>&2; exit 1;;
- esac
- X
- X: set up for file suffix processing
- X
- case $LANG in
- X"") sh='[:#]'; r='#'; rh=$r; awk='#'; mk='#';
- X c='\/\*'; h=$c; y=$c; l=$c;
- X f='[Cc]'; fh=$f; p='{'; ph=$p;
- X ms='\\"'; nr=$ms; mn=$ms; man=$ms;
- esac
- X
- X: extract comments
- X
- for i in $*
- do
- X case $LANG in
- X "") eval B\="\$`expr $i : '^.*\.\([^.]*\)$'`"
- X test "$B" || { echo "$0: unknown suffix: $i; assuming c" 1>&2; B=$c; }
- X esac
- X sed '
- X /^'"$B"'++/,/^'"$B"'--/!d
- X /^'"$B"'++/d
- X /^'"$B"'--/d
- X s/[ ]*$//
- X /^'"$B"' \([A-Z]\)/{
- X s//\1/
- X /^NAME/{
- X N
- X s/^.*\n'"$B"'[ ]*//
- X h
- X y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
- X s/,.*\([ ][0-9][ ]*\)$/ \1/
- X s/^.*$/.TH & '"$SECT $LOCAL $HOST"'\
- X.ad\
- X.fi\
- X.SH NAME/
- X p
- X g
- X s/[ ][0-9][ ]*$//
- X a\
- X\\-
- X p
- X d
- X }
- X /^SUMMARY/d
- X /^DESCRIPTION/s//.SH &\
- X.ad\
- X.fi/
- X /^BUGS/s//.SH &\
- X.ad\
- X.fi/
- X /^DIAGNOSTICS/s//.SH &\
- X.ad\
- X.fi/
- X /^[A-Z][A-Z][A-Z][^a-z]*$/s//.SH &\
- X.na\
- X.nf/
- X p
- X d
- X }
- X s/^'"$B"'[ ]*//
- X s/^[ ]*$//
- X' $i
- done | ./detab
- X
- exit
- X
- X:++
- X: NAME
- X: srctoman 1
- X: SUMMARY
- X: extract manual page from source file comment
- X: PACKAGE
- X: source file maintentance tools
- X: SYNOPSIS
- X: srctoman [-|-awk|-c|-f|-mk|-m|-n|-p|-t|-r] [section] file(s)
- X: DESCRIPTION
- X: Sourcetoman converts comments in various programming languages to
- X: UNIX-style manual pages.
- X: The command processes comments in the style of newsource(1);
- X: its standard output is suitable for formatting with nroff(1) or
- X: troff(1) using the "-man" macro package.
- X: Typically, srctoman is integrated with make(1) scripts.
- X: If the option -L is given the text <hostname> (LOCAL) will be in
- X: the heading.
- X:
- X: Source files are processed in the indicated order; if no
- X: files argument the command produces no output.
- X:
- X: The source file language can be specified through a command-line
- X: option, or can be implied by the filename suffix.
- X: The expected start-of-comment symbol is shown in the last column.
- X:
- X: .nf
- X option language comment
- X
- X - shell [:#]
- X -awk awk #
- X -c c /*
- X -f fortran [Cc]
- X -mk make #
- X -n nroff \\"
- X -p pascal {
- X -t troff \\"
- X -r ratfor #
- X -C any language next argument
- X: .fi
- X:
- X: .nf
- X suffix language comment
- X
- X .awk awk #
- X .c c /*
- X .f fortran [Cc]
- X .fh fortran [Cc]
- X .h c /*
- X .l lex /*
- X .man nroff,troff \\"
- X .mk make #
- X .me nroff,troff \\"
- X .ms nroff,troff \\"
- X .nr nroff,troff \\"
- X .p pascal {
- X .ph pascal {
- X .r ratfor #
- X .rh ratfor #
- X .sh shell [:#]
- X .y yacc /*
- X: .fi
- X:
- X: The required format of comments is discussed below, where SOC
- X: stands for the start-of-comment symbol of the language being used.
- X:
- X: 1) Start of manual: SOC, followed by `++'.
- X:
- X: 2) Section heading: SOC, blank, section name in upper case.
- X:
- X: 3) New paragraph: empty line or line with SOC only.
- X:
- X: 4) All other text: SOC and subsequent blanks or tabs are removed.
- X: Lines that do not start with SOC are left unchanged (useful for
- X: inclusion of program text).
- X:
- X: 5) End of manual: SOC, followed by `--'.
- X: An end-of-comment may follow if the source file language requires this.
- X:
- X: The following manual sections receive a special treatment:
- X: NAME and SUMMARY should appear at the beginning and in
- X: this order; DESCRIPTION, DIAGNOSTICS and BUGS will be
- X: right-margin adjusted.
- X: Other sections may be added freely without confusing srctoman.
- X: COMMANDS
- X: sh(1), sed(1), detab(1)
- X: SEE ALSO
- X: newsource(1), modsource(1), xman(1)
- X: The earlier commands new(1), mod(1), mkman(1) and dssman(1)
- X: by Ruud Zwart and Ben Noordzij (Erasmus University, Rotterdam)
- X: DIAGNOSTICS
- X: The program complaints if an unknown language is specified
- X: of if the language cannot be deduced from the file suffix.
- X: AUTHOR(S)
- X: W.Z. Venema
- X: Eindhoven University of Technology
- X: Department of Mathematics and Computer Science
- X: Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X: CREATION DATE
- X: Fri Jan 17 22:59:27 MET 1986
- X: LAST MODIFICATION
- X: Tue Mar 22 07:24:47 PST 1988
- X: VERSION/RELEASE
- X: 1.20
- X:--
- X
- X
- END_OF_FILE
- if test 4703 -ne `wc -c <'srctoman'`; then
- echo shar: \"'srctoman'\" unpacked with wrong size!
- fi
- # end of 'srctoman'
- fi
- if test -f 'sysdep' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sysdep'\"
- else
- echo shar: Extracting \"'sysdep'\" \(268 characters\)
- sed "s/^X//" >'sysdep' <<'END_OF_FILE'
- X#define XSYSTEM
- X#define XSYSLOG
- X#define COMMANDS "XCOMMANDS"
- X#define PROFILE "XPROFILE"
- X
- X#ifndef _NFILE
- X#include <sys/param.h>
- X#define _NFILE NOFILE
- X#endif
- X
- X#ifdef SYSV
- X#include <string.h>
- X#else
- X#include <strings.h>
- X#define strchr index
- X#define strrchr rindex
- X#endif
- END_OF_FILE
- if test 268 -ne `wc -c <'sysdep'`; then
- echo shar: \"'sysdep'\" unpacked with wrong size!
- fi
- # end of 'sysdep'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-